package com.atguigu.gmall.realtime.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.realtime.common.GmallConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hbase.client.Connection;
import redis.clients.jedis.Jedis;

/**
 * @author Felix
 * @date 2023/12/28
 * 查询维度的工具类
 */
public class DimUtil {
    /**
     * 根据主键查询维度数据
     * 优化：旁路缓存
     *  旁路缓存思路：先从缓存中获取维度数据，如果在缓存中找到了要关联的维度，直接作为方法的返回值进行返回(缓存命中)
     *              如果在缓存中没有找到要关联的维度，发送请求到hbase中查询维度，并将查询出的维度放到缓存中缓存
     *              起来，方便下次查询使用。
     *  缓存产品选型：
     *          状态：  性能更好   维护性差
     *          redis：性能也不错，维护性好    √
     *  关于Redis中的设置：
     *          类型： String
     *          key： 维度表表名:主键值      例如：dim_base_trademark:1
     *          expire:  1day    为了避免冷数据常驻内存，给内存带来压力，设置失效时间
     *          注意：如果维度数据发生了变化，那么缓存的维度也应该被清除
     * @param redisClient       redis的客户端jedis
     * @param hbaseConn         hbase的连接
     * @param nameSpace         表空间
     * @param tableName         表名
     * @param rowkey            rowkey
     * @return
     */
    public static JSONObject getDimInfo(Jedis redisClient, Connection hbaseConn,String nameSpace,String tableName,String rowkey){
        //拼接从Redis中查询数据的key
        String redisKey =  tableName.toLowerCase() + ":" + rowkey;
        //用于接收从Redis中查询的数据
        String dimJsonStr = null;
        //用于封装返回的结果
        JSONObject dimJsonObj = null;

        // 先从缓存中获取维度数据
        dimJsonStr = redisClient.get(redisKey);

        //判断是否缓存命中
        if(StringUtils.isNotEmpty(dimJsonStr)){
            // 如果在缓存中找到了要关联的维度，直接作为方法的返回值进行返回（缓存命中）
            System.out.println("~~~从Redis中获取到"+tableName+"的"+rowkey+"数据~~~");
            dimJsonObj = JSON.parseObject(dimJsonStr);
        }else{
            System.out.println("~~~从Hbase中获取到"+tableName+"的"+rowkey+"数据~~~");
            // 如果在缓存中没有找到要关联的维度，发送请求到hbase中查询维度
            dimJsonObj = HbaseUtil.getDimInfoFromHbase(hbaseConn,nameSpace,tableName,rowkey);
            //将查询出的维度放到缓存中缓存起来，方便下次查询使用
            redisClient.setex(redisKey,24*3600,dimJsonObj.toJSONString());
        }

        return dimJsonObj;
    }

    public static void main(String[] args) {
        Jedis redisClient = RedisUtil.getRedisClient();
        Connection hbaseConn = HbaseUtil.getHbaseConnection();
        System.out.println(getDimInfo(redisClient, hbaseConn, GmallConfig.HBASE_NAMESPACE, "dim_base_trademark", "2"));
        HbaseUtil.closeHbaseConnection(hbaseConn);
        RedisUtil.closeRedisClient(redisClient);
    }

    //删除缓存的维度数据
    public static void delCached(String tableName,String id){
        //拼接操作Redis的key
        String redisKey = tableName.toLowerCase() + ":" + id;
        Jedis redisClient = RedisUtil.getRedisClient();
        System.out.println("~~~从Redis中删除"+tableName+"的"+id+"数据~~~");
        redisClient.del(redisKey);
        RedisUtil.closeRedisClient(redisClient);
    }
}
